package aos.maekawa;

import java.util.HashMap;
import java.util.Vector;

import aos.maekawa.entity.GlobalVariables;
import aos.maekawa.entity.Message;
import aos.maekawa.entity.MessageType;
import aos.maekawa.entity.RoutineData;
import aos.maekawa.log.LogUtils;

public class CSRoutine implements Runnable {

	private int nodeId;
	private ProcessorNode processorNode;
	private Object synObject;

	public CSRoutine(ProcessorNode processorNode, Object synObject) {
		this.processorNode = processorNode;
		this.nodeId = this.processorNode.getNodeId();
		this.synObject = synObject;
	}

	@Override
	public void run() {
		int m = RoutineData.m;
		int reqId = 0;
		int ia = RoutineData.ia;
		int cst = RoutineData.cst;
		HashMap<Integer, Vector<Integer>> quorumList = RoutineData.quorumList;
		while (reqId++ < m) {
			Vector<Integer> q = quorumList.get(nodeId);
			for (Integer toNodeId : q) {
				Message msg = new Message();
				msg.setMsgType(MessageType.REQUEST);
				msg.setFromId(nodeId);
				msg.setToId(toNodeId);
				msg.setCst(cst);
				try {
					processorNode.sendMessage(msg);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			synchronized (synObject) {
				try {
					LogUtils.debugLog("synObject wait");
					synObject.wait();
					LogUtils.debugLog("synObject awake");
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			try {
				Thread.sleep(ia);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		Message msg = new Message();
		msg.setMsgType(MessageType.REPORT);
		msg.setFromId(nodeId);
		msg.setToId(GlobalVariables.masterId);
		msg.setReport(processorNode.getReport());
		try {
			processorNode.sendMessage(msg);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
